/****************************************************************************/
/* NAME:           command.c                                                */
/* PURPOSE:        Leds pwm management                                      */
/* CREATED_BY:     Didsau                                                   */
/* CREATION_DATE:  02/07/2013                                               */
/* MODIFIED_BY:    Vyx                                                      */
/************************************** (C) Copyright 2013 AquaLink *********/

#include "command.h"
#include "temperature.h"
#include "osmolator.h"
#include "oscillator.h"
#include <stdlib.h>

#define MAX_INPUT_LENGTH    (50)
#define MAX_OUTPUT_LENGTH   (100)

#define MIN_INT_LENGHT      (1)
#define MAX_INT_LENGHT      (65535)

bool LocalEcho;
const int8_t pcPS1[] = "\r\n[aqualink ~]$> ";

/**
 * Welcome text
 */
const int8_t pcWelcomeMessage[] = "\
  ___                    _     _       _    \r\n\
 / _ \\                  | |   (_)     | |   \r\n\
/ /_\\ \\ __ _ _   _  __ _| |    _ _ __ | | __\r\n\
|  _  |/ _` | | | |/ _` | |   | | '_ \\| |/ /\r\n\
| | | | (_| | |_| | (_| | |___| | | | |   < \r\n\
\\_| |_/\\__, |\\__,_|\\__,_\\_____/_|_| |_|_|\\_\\\r\n\
          | |                               \r\n\
          |_|                               \r\n\
\r\n\
\r\n\
*** Enter Help to see command list ***\r\n";

const int8_t pcParameterError_1[]   = "Error : Parameter ";
const int8_t pcParameterError_2[]   = " not supported\r\n";
const int8_t pcWaterLevel[3][6]     = {"Low", "Middle", "High"};
const int8_t pcOscillatorMode[2][6] = {"Random", "Linear"};

/******************************************************************************/
/*                                                                            */
/*  COMMANDS LIST DEFINTION                                                   */
/*                                                                            */
/******************************************************************************/

/******************************************************************************/
/* SYSTEM COMMAND                                                             */
/******************************************************************************/
const CLI_Command_Definition_t xEchoTempCommand =
{
  (const int8_t * const) "echo",
  (const int8_t * const) "-> echo [0, 1]\r\n",
  prvTask_Echo_Command,
  1
};

/******************************************************************************/
/* TEMPERATURE MODULE COMMAND                                                 */
/******************************************************************************/
const CLI_Command_Definition_t xGetWaterTempCommand =
{
  (const int8_t * const) "getwatertemp",                                        // command name
  (const int8_t * const) "-> getwatertemp\r\n",                                 // command help text
  prvTask_GetWaterTemp_Command,                                                 // command callback
  0                                                                             // command nb parameter
};
const CLI_Command_Definition_t xWaterSetpointCommand =
{
  (const int8_t * const) "watersetpoint",
  (const int8_t * const) "-> watersetpoint [get,set] : water setpoint\r\n",
  prvTask_WaterSetpoint_Command,
  2
};
/******************************************************************************/
/* OSMOLATOR MODULE COMMAND                                                   */
/******************************************************************************/
const CLI_Command_Definition_t xOsmolatorModeCommand =
{
  (const int8_t * const) "osmolatormode",
  (const int8_t * const) "-> osmolatormode Nb sensor[0, 1, 2] Reserve[0, 1]\r\n",
  prvTask_OsmolatorMode_Command,
  2
};
const CLI_Command_Definition_t xGetWaterLevelCommand =
{
  (const int8_t * const) "getwaterlevel",
  (const int8_t * const) "-> getwaterlevel\r\n",
  prvTask_GetWaterLevel_Command,
  0
};
/******************************************************************************/
/* OSCILLATOR MODULE COMMAND                                                  */
/******************************************************************************/
const CLI_Command_Definition_t xSetOscillatorCommand =
{
  (const int8_t * const) "setoscilator",
  (const int8_t * const) "-> setoscillator Osci Nb[1, 2] Param[mode, speed, min, max, pause] ParamValue[]\r\n",
  prvTask_SetOscillator_Command,
  3
};
const CLI_Command_Definition_t xGetOscillatorCommand =
{
  (const int8_t * const) "getoscilator",
  (const int8_t * const) "-> getoscillator Osci Nb[1, 2] =\r\n",
  prvTask_GetOscillator_Command,
  1
};

/******************************************************************************/
/*                                                                            */
/*  END COMMANDS LIST DEFINTION                                               */
/*                                                                            */
/******************************************************************************/

/**
 * @brief  Register all commands, call one time at start
 */
void RegisterCommands(void)
{

  FreeRTOS_CLIRegisterCommand(&xEchoTempCommand);

  FreeRTOS_CLIRegisterCommand(&xGetWaterTempCommand);
  FreeRTOS_CLIRegisterCommand(&xWaterSetpointCommand);

  FreeRTOS_CLIRegisterCommand(&xOsmolatorModeCommand);
  FreeRTOS_CLIRegisterCommand(&xGetWaterLevelCommand);

  FreeRTOS_CLIRegisterCommand(&xSetOscillatorCommand);
  FreeRTOS_CLIRegisterCommand(&xGetOscillatorCommand);
}

/**
 * @brief  Commands task manager
 */
void vTaskCTRL_COMMANDS()
{
  static int8_t pcOutputString[ MAX_OUTPUT_LENGTH ];
  static int8_t pcInputString[ MAX_INPUT_LENGTH ];
  portTickType  xLastWakeTime;
  int8_t        cRxedChar;
  int8_t        cInputIndex;
  portBASE_TYPE xMoreDataToFollow;

  cInputIndex   = 0;
  xLastWakeTime = xTaskGetTickCount();

  /* register all commands */
  RegisterCommands();

  /* Send a welcome message to the user knows they are connected. */
  printf("%s", pcWelcomeMessage);

  /* send command invitation */
  printf("%s", pcPS1);

  while(1)
  {
    /* Read char from UART */
    scanf("%c", &cRxedChar);

    if( cRxedChar == '\n' )
    {
      /* Send new line before command response */
      printf("\r\n");

      /* The command interpreter is called repeatedly until it returns pdFALSE */
      do
      {
        /* Send the command string to the command interpreter */
        xMoreDataToFollow = FreeRTOS_CLIProcessCommand(pcInputString,   	/* The command string.*/
                                                       pcOutputString,  	/* The output buffer. */
                                                       MAX_OUTPUT_LENGTH);	/* The size of the output buffer. */

        /* Write the output generated by the command interpreter to the console. */
        printf("%s", pcOutputString);

      }
      while( xMoreDataToFollow != pdFALSE );

      /* clean buffer reception */
      cInputIndex = 0;
      memset( pcInputString, 0x00, MAX_INPUT_LENGTH );

      wait(5);

      /* send command invitation for next command */
      printf("%s", pcPS1);
    }
    else
    {
      /* The if() clause performs the processing after a newline character
            is received.  This else clause performs the processing if any other
            character is received. */

      if( cRxedChar == '\r' )
      {
        /* Ignore carriage returns. */
      }
      else if( cRxedChar == '\b' )
      {
        /* Backspace was pressed.  Erase the last character in the input
                buffer - if there are any. */
        if( cInputIndex > 0 )
        {
          cInputIndex--;
          pcInputString[cInputIndex] = '\0';

          #ifdef LOCAL_ECHO
              if (LocalEcho != FALSE)
              {
                  /* send backspace echo */
                  printf("\b"); /* Hex ASCI code : 0x08 */
              }
          #endif
        }
      }
      else
      {
        /* A character was entered.  It was not a new line, backspace
                or carriage return, so it is accepted as part of the input and
                placed into the input buffer.  When a \n is entered the complete
                string will be passed to the command interpreter. */
        if( cInputIndex < MAX_INPUT_LENGTH )
        {
          pcInputString[ cInputIndex ] = cRxedChar;
          cInputIndex++;

          #ifdef LOCAL_ECHO
          	  if (LocalEcho != FALSE)
          	  {
          		  /* send echo */
          		  printf("%c", cRxedChar);
          	  }
          #endif
        }
      }
    }
  }
}


/******************************************************************************/
/*                                                                            */
/*  COMMANDS DEFINTION                                                        */
/*                                                                            */
/******************************************************************************/

/**
 * @brief  Manage echo
 * @param  None
 * @retval None
 */
portBASE_TYPE prvTask_Echo_Command(int8_t *pcWriteBuffer,
                                   size_t xWriteBufferLen,
                                   const int8_t *pcCommandString)
{
	portBASE_TYPE xParameter1StringLength;
	int8_t        *pcParameter1;

	pcParameter1 = FreeRTOS_CLIGetParameter(pcCommandString,
	                                        1,
	                                        &xParameter1StringLength);

  pcParameter1[xParameter1StringLength] = 0x00;

	if ((strncmp((char*)pcParameter1, "0", xParameter1StringLength) == 0)       ||
		(strncmp((char*)pcParameter1, "1", xParameter1StringLength) == 0))
	{
		LocalEcho = atoi((char*)pcParameter1);
	}
	else
	{
	  snprintf((char*)pcWriteBuffer, xWriteBufferLen , "%s%d%s", pcParameterError_1, 1, pcParameterError_2);
	}

	return pdFALSE;
}

/**
 * @brief  Return de water temp
 * @param  None
 * @retval None
 */
portBASE_TYPE prvTask_GetWaterTemp_Command(int8_t *pcWriteBuffer,
                                           size_t xWriteBufferLen,
                                           const int8_t *pcCommandString)
{
  double temp;

  /* not used */
  (void) pcCommandString;

  /* read temp */
  ReadDebouncedTemp(&temp, FAN_WATER);

  /* display temp in string line */
  snprintf((char*)pcWriteBuffer, xWriteBufferLen , "Water temp : %f\r\n", temp);

  return pdFALSE;
}

/**
 * @brief  water set point management
 * @param  None
 * @retval None
 */
portBASE_TYPE prvTask_WaterSetpoint_Command(int8_t *pcWriteBuffer,
                                            size_t xWriteBufferLen,
                                            const int8_t *pcCommandString)
{
  portBASE_TYPE xParameter1StringLength;
  portBASE_TYPE xParameter2StringLength;
  int8_t        *pcParameter1;
  int8_t        *pcParameter2;
  double        setPoint;

  pcParameter1 = FreeRTOS_CLIGetParameter(pcCommandString,
                                          1,
                                          &xParameter1StringLength);
  pcParameter2 = FreeRTOS_CLIGetParameter(pcCommandString,
                                          2,
                                          &xParameter2StringLength);

  pcParameter1[xParameter1StringLength] = 0x00;
  pcParameter2[xParameter2StringLength] = 0x00;

  if (strncmp((char*)pcParameter1, "get", xParameter1StringLength) == 0)
  {
      TEMP_GetSetpointTemp(&setPoint, FAN_WATER);
  }
  else
  {
    if (strncmp((char*)pcParameter1, "set", xParameter1StringLength) == 0)
    {
      setPoint = atoi((char*)pcParameter2);

      if (setPoint < 0.0 && setPoint > 99.9)
      {
        setPoint = 25.0;
      }

      TEMP_SetSetpointTemp(&setPoint, FAN_WATER);
    }
  }

  /* display setpoint in string line */
  snprintf((char*)pcWriteBuffer, xWriteBufferLen , "Water setpoint : %f\r\n", setPoint);

  return pdFALSE;
}

/**
 * @brief  Set osmolator mode
 * @param  None
 * @retval None
 */
portBASE_TYPE prvTask_OsmolatorMode_Command(int8_t *pcWriteBuffer,
                                            size_t xWriteBufferLen,
                                            const int8_t *pcCommandString)
{
  portBASE_TYPE xParameter1StringLength;
  portBASE_TYPE xParameter2StringLength;
  int8_t        *pcParameter1;
  int8_t        *pcParameter2;

  pcParameter1 = FreeRTOS_CLIGetParameter(pcCommandString,
                                          1,
                                          &xParameter1StringLength);
  pcParameter2 = FreeRTOS_CLIGetParameter(pcCommandString,
                                          2,
                                          &xParameter2StringLength);

  pcParameter1[xParameter1StringLength] = 0x00;
  pcParameter2[xParameter2StringLength] = 0x00;

  if (((strncmp((char*)pcParameter1, "0", xParameter1StringLength) == 0)      ||
       (strncmp((char*)pcParameter1, "1", xParameter1StringLength) == 0)      ||
       (strncmp((char*)pcParameter1, "2", xParameter1StringLength) == 0))
     &&
      ((strncmp((char*)pcParameter2, "0", xParameter2StringLength) == 0)      ||
       (strncmp((char*)pcParameter2, "1", xParameter2StringLength) == 0)))
  {
    Osmo_SetMode(atoi((char*)pcParameter1), atoi((char*)pcParameter2));
  }
  else
  {
    snprintf((char*)pcWriteBuffer, xWriteBufferLen , "%s%s%s", pcParameterError_1, "1 or 2", pcParameterError_2);
  }

  return pdFALSE;
}

/**
 * @brief  Return water level
 * @param  None
 * @retval None
 */
portBASE_TYPE prvTask_GetWaterLevel_Command(int8_t *pcWriteBuffer,
                                           size_t xWriteBufferLen,
                                           const int8_t *pcCommandString)
{
  /* not used */
  (void) pcCommandString;

  /* display water level */
  snprintf((char*)pcWriteBuffer, xWriteBufferLen , "Water level : %s\r\n", pcWaterLevel[Osmo_GetWaterLevel()]);

  return pdFALSE;
}

/**
 * @brief  Set oscillator
 * @param  None
 * @retval None
 */
portBASE_TYPE prvTask_SetOscillator_Command(int8_t *pcWriteBuffer,
                                            size_t xWriteBufferLen,
                                            const int8_t *pcCommandString)
{
  portBASE_TYPE xParameter1StringLength;
  portBASE_TYPE xParameter2StringLength;
  portBASE_TYPE xParameter3StringLength;
  int8_t        *pcParameter1;
  int8_t        *pcParameter2;
  int8_t        *pcParameter3;

  pcParameter1 = FreeRTOS_CLIGetParameter(pcCommandString,
                                          1,
                                          &xParameter1StringLength);
  pcParameter2 = FreeRTOS_CLIGetParameter(pcCommandString,
                                          2,
                                          &xParameter2StringLength);
  pcParameter3 = FreeRTOS_CLIGetParameter(pcCommandString,
                                          3,
                                          &xParameter3StringLength);

  pcParameter1[xParameter1StringLength] = 0x00;
  pcParameter2[xParameter2StringLength] = 0x00;
  pcParameter3[xParameter2StringLength] = 0x00;

  if ((strncmp((char*)pcParameter1, "1",  xParameter1StringLength) == 0)      ||
      (strncmp((char*)pcParameter1, "2",  xParameter1StringLength) == 0))
  {
    if ((strncmp((char*)pcParameter2, "mode",  xParameter2StringLength) == 0) ||
        (strncmp((char*)pcParameter2, "speed", xParameter2StringLength) == 0) ||
        (strncmp((char*)pcParameter2, "min",   xParameter2StringLength) == 0) ||
        (strncmp((char*)pcParameter2, "max",   xParameter2StringLength) == 0) ||
        (strncmp((char*)pcParameter2, "pause", xParameter2StringLength) == 0))
    {
      if (strncmp((char*)pcParameter2, "mode", xParameter2StringLength) == 0)
      {
        if (strncmp((char*)pcParameter3, "linear", xParameter3StringLength) == 0)
        {
          Osci_SetMode(atoi((char*)pcParameter1), TRUE);
        }
        else if (strncmp((char*)pcParameter3, "random", xParameter3StringLength) == 0)
        {
          Osci_SetMode(atoi((char*)pcParameter1), FALSE);
        }
        else
        {
          snprintf((char*)pcWriteBuffer, xWriteBufferLen , "%s%d%s", pcParameterError_1, 3, pcParameterError_2);
        }
      }
      else if (strncmp((char*)pcParameter2, "speed",  xParameter2StringLength) == 0)
      {
        if (atoi((char*)pcParameter3) >= MIN_INT_LENGHT && atoi((char*)pcParameter3) <= MAX_INT_LENGHT)
        {
          Osci_SetSpeed(atoi((char*)pcParameter1), atoi((char*)pcParameter3));
        }
        else
        {
          snprintf((char*)pcWriteBuffer, xWriteBufferLen , "%s%d%s", pcParameterError_1, 3, pcParameterError_2);
        }
      }
      else if (strncmp((char*)pcParameter2, "min",  xParameter2StringLength) == 0)
      {
        if (atoi((char*)pcParameter3) >= MIN_INT_LENGHT && atoi((char*)pcParameter3) <= MAX_INT_LENGHT)
        {
          Osci_SetMin(atoi((char*)pcParameter1), atoi((char*)pcParameter3));
        }
        else
        {
          snprintf((char*)pcWriteBuffer, xWriteBufferLen , "%s%d%s", pcParameterError_1, 3, pcParameterError_2);
        }
      }
      else if (strncmp((char*)pcParameter2, "max",  xParameter2StringLength) == 0)
      {
        if (atoi((char*)pcParameter3) >= MIN_INT_LENGHT && atoi((char*)pcParameter3) <= MAX_INT_LENGHT)
        {
          Osci_SetMax(atoi((char*)pcParameter1), atoi((char*)pcParameter3));
        }
        else
        {
          snprintf((char*)pcWriteBuffer, xWriteBufferLen , "%s%d%s", pcParameterError_1, 3, pcParameterError_2);
        }
      }
      else if (strncmp((char*)pcParameter2, "pause",  xParameter2StringLength) == 0)
      {
        if (atoi((char*)pcParameter3) >= MIN_INT_LENGHT && atoi((char*)pcParameter3) <= MAX_INT_LENGHT)
        {
          Osci_SetPause(atoi((char*)pcParameter1), atoi((char*)pcParameter3));
        }
        else
        {
          snprintf((char*)pcWriteBuffer, xWriteBufferLen , "%s%d%s", pcParameterError_1, 3, pcParameterError_2);
        }
      }
      else
      {
        snprintf((char*)pcWriteBuffer, xWriteBufferLen , "%s%d%s", pcParameterError_1, 2, pcParameterError_2);
      }
    }
    else
    {
      snprintf((char*)pcWriteBuffer, xWriteBufferLen , "%s%d%s", pcParameterError_1, 2, pcParameterError_2);
    }
  }
  else
  {
    snprintf((char*)pcWriteBuffer, xWriteBufferLen , "%s%d%s", pcParameterError_1, 1, pcParameterError_2);
  }

  return pdFALSE;
}

/**
 * @brief  Set oscillator
 * @param  None
 * @retval None
 */
portBASE_TYPE prvTask_GetOscillator_Command(int8_t *pcWriteBuffer,
                                            size_t xWriteBufferLen,
                                            const int8_t *pcCommandString)
{
  int8_t        *pcParameter1;
  portBASE_TYPE xParameter1StringLength;

  pcParameter1 = FreeRTOS_CLIGetParameter(pcCommandString, 1, &xParameter1StringLength);

  pcParameter1[xParameter1StringLength] = 0x00;

  if ((strncmp((char*)pcParameter1, "1",  xParameter1StringLength) == 0)      ||
      (strncmp((char*)pcParameter1, "2",  xParameter1StringLength) == 0))
  {
      snprintf((char*)pcWriteBuffer, xWriteBufferLen , "\r\n- Mode = %s \r\n- Speed = %ld \r\n- Pause = %ld \r\n- Min Position = %d \r\n- Max position = %d\r\n",
                                                       pcOscillatorMode[Osci_GetMode(atoi((char*)pcParameter1))],
                                                       Osci_GetSpeed(atoi((char*)pcParameter1)),
                                                       Osci_GetPause(atoi((char*)pcParameter1)),
                                                       Osci_GetMin(atoi((char*)pcParameter1)),
                                                       Osci_GetMax(atoi((char*)pcParameter1)));
  }
  else
  {
    snprintf((char*)pcWriteBuffer, xWriteBufferLen , "%s%d%s", pcParameterError_1, 1, pcParameterError_2);
  }

  return pdFALSE;
}




/******************************************************************************/
/*                                                                            */
/*  END COMMANDS DEFINTION                                                    */
/*                                                                            */
/******************************************************************************/





